﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Prism.Commands;
using WeiboPlus.Common;
using WeiboPlus.Models;
using WeiboPlus.Service;
using WeiboPlus.ViewModel;

namespace WeiboPlus.Shell.ViewModel
{
    public class UserHomeViewModel : CollectionVMBase<SNSStatusViewModel>
    {
        private int retry = 0;

        bool isFolloing;

        public bool IsFolloing
        {
            get { return isFolloing; }
            set { isFolloing = value; RaisePropertyChanged(() => IsFolloing); }
        }
        private SNSPagingInfo _pagingInfo;
        private int pagecount = 10;
        private IStatusService _statusSvc;
        private IUserService _userSvc;
        int _pageFirends = 0;
        int _pageFollowers = 0;
        int _cursorFriend = -1;
        int _cursorFollower = -1;
        SNSUser _user;
        public SNSUser User
        {
            get
            {
                return _user;
            }
            set
            {
                _user = value;
                RaisePropertyChanged("User");
            }
        }

        ImageSource profileImage;
        public ImageSource ProfileImage
        {
            get { return profileImage; }
            set
            {
                profileImage = value;
                RaisePropertyChanged("ProfileImage");
            }
        }

        ObservableCollection<SNSUser> _followers = new ObservableCollection<SNSUser>();
        public ObservableCollection<SNSUser> Followers
        {
            get
            {
                return _followers;
            }
            set
            {
                _followers = value;
                RaisePropertyChanged(() => Followers);
            }
        }

        ObservableCollection<SNSUser> _friends = new ObservableCollection<SNSUser>();
        public ObservableCollection<SNSUser> Friends
        {
            get
            {
                return _friends;
            }
            set
            {
                _friends = value;
                RaisePropertyChanged(() => Friends);
            }
        }

        public DelegateCommand Follow { get; set; }

        public DelegateCommand Unfollow { get; set; }

        public DelegateCommand SendMessage { get; set; }

        public Action OnTweetsRefreshed { get; set; }

        public Action OnFriendsRefreshed { get; set; }

        public Action OnFollowersRefreshed { get; set; }

        public Action OnNextPageOfTweetsPerformed { get; set; }

        public Action OnNextPageOfFriendsPerformed { get; set; }

        public Action OnNextPageOfFollowersPerformed { get; set; }

        public UserHomeViewModel(string name, int accountID)
        {
            var account = AccountManager.Current.GetAccount(accountID);
            if (account == null)
                throw new Exception("Account not existed");
            _statusSvc = PhoneApplicationController.Current.Container.Resolve<IStatusService>(account.ServiceProvider.ToString());
            _statusSvc.FactoryResolver = () => SNSProviderManager.CreateFactory(account);
            _statusSvc.ProviderResolver = () => SNSProviderManager.GetFactory(account).GetProvider();
            _statusSvc.Account = account;
            _userSvc = PhoneApplicationController.Current.Container.Resolve<IUserService>(account.ServiceProvider.ToString());
            _userSvc.FactoryResolver = () => SNSProviderManager.CreateFactory(account);
            _userSvc.ProviderResolver = () => SNSProviderManager.GetFactory(account).GetProvider();
            _userSvc.Account = account;

            Follow = new DelegateCommand(FollowMethod, () => { return !Loading; });
            Unfollow = new DelegateCommand(UnfollowMethod, () => { return !Loading; });
            SendMessage = new DelegateCommand(SendMessageMethod, () => { return !Loading; });

            if (_statusSvc != null)
            {
                if (User == null)
                {
                    User = new SNSUser
                    {
                        AccountID = account.AccountID,
                        AccountName = name
                    };
                }

                LoadData();
            }
        }

        public UserHomeViewModel(SNSUser user)
        {
            User = user;

            var account = AccountManager.Current.GetAccount(user.AccountID);

            _statusSvc = PhoneApplicationController.Current.Container.Resolve<IStatusService>(account.ServiceProvider.ToString());
            _statusSvc.ProviderResolver = () => SNSProviderManager.GetFactory(account).GetProvider();
            _statusSvc.FactoryResolver = () => SNSProviderManager.CreateFactory(account);
            _statusSvc.Account = account;
            _userSvc = PhoneApplicationController.Current.Container.Resolve<IUserService>(account.ServiceProvider.ToString());
            _userSvc.ProviderResolver = () => SNSProviderManager.GetFactory(account).GetProvider();
            _userSvc.FactoryResolver = () => SNSProviderManager.CreateFactory(account);
            _userSvc.Account = account;
            //TODO: New account

            Follow = new DelegateCommand(FollowMethod, () => { return !Loading; });
            Unfollow = new DelegateCommand(UnfollowMethod, () => { return !Loading; });
            SendMessage = new DelegateCommand(SendMessageMethod, () => { return !Loading; });

            if (User != null && _statusSvc != null)
            {
                ExecuteOnUIThread(() =>
               {
                   LoadData();
               });
            }
        }

        public new void LoadData()
        {
            GetUserInfo();
        }

        private void GetFriendship()
        {
            Loading = true;

            _userSvc.GetFriendship(_user, (f, r) =>
            {
                ExecuteOnUIThread(() =>
                {
                    if (!r.IsSuccess)
                    {
                        MessageBox.Show(r.Message);
                    }
                    else
                    {
                        _user.Following = IsFolloing = f.Source.Following;
                        //_user.Following = !_user.Following;
                    }

                    Loading = false;
                });
            });

        }

        private void GetUserInfo()
        {
            if (User != null && _userSvc != null)
            {
                var request = new SNSRequest() { Type = SNSType.SingleUser };
                request.Parameters.Add(new SNSParameter(SNSParametersConstants.NAME, User.AccountName));

                //for renren
                request.Parameters.Add(new SNSParameter(SNSParametersConstants.UID, User.Id.ToString()));
                //for sina 
                request.Parameters.Add(new SNSParameter(SNSParametersConstants.SCREEN_NAME, User.AccountName));

                _userSvc.GetUser(request, (u, r) =>
                {
                    ExecuteOnUIThread(() =>
                    {
                        if (!r.IsSuccess)
                        {
                            MessageBox.Show(r.Message);
                        }
                        else
                        {
                            if (u == null && retry < 3)
                            {
                                retry++;
                                GetUserInfo();
                                return;
                            }

                            User = u;
                            RefreshTimeLineOfTweets(true);

                            if (User.ServiceProvider == SNSProviderType.Sina)
                                GetFriendship();
                        }
                        //Loading = false;
                    });
                });
            }
            //throw new NotImplementedException();
        }

        public void FollowMethod()
        {
            Loading = true;

            _userSvc.Follow(_user, (u, r) =>
            {
                ExecuteOnUIThread(() =>
                {
                    if (!r.IsSuccess)
                    {
                        MessageBox.Show(r.Message);
                    }
                    else
                    {

                        IsFolloing = _user.Following = !_user.Following;
                    }

                    Loading = false;
                });
            });
        }

        public void UnfollowMethod()
        {
            Loading = true;

            _userSvc.Unfollow(_user, (u, r) =>
            {
                ExecuteOnUIThread(() =>
                {
                    if (!r.IsSuccess)
                    {
                        MessageBox.Show(r.Message);
                    }
                    else
                    {

                        IsFolloing = _user.Following = !_user.Following;
                    }

                    Loading = false;
                });
            });
        }

        public void SendMessageMethod()
        {
            MessageBox.Show(AppResx.DevInProgressText, AppResx.InfoText, MessageBoxButton.OK);
        }

        internal void NextPageOfTweets(bool isFirstTime)
        {
            SNSRequest request = null;
            string pageflag = "1";

            var items = Items;
            request = new SNSRequest() { Type = SNSType.UserStatus };

            if (!isFirstTime && items.Count < pagecount)
                return;

            switch (User.ServiceProvider)
            {
                case SNSProviderType.Sina:
                    var firstItemSina = items.LastOrDefault();
                    if (firstItemSina != null)
                    {
                        var id = firstItemSina.Item.Id - 1;
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.MAX_ID, id + string.Empty));
                    }
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.COUNT, pagecount + string.Empty));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.USER_ID, User.Id.ToString()));
                    break;
                case SNSProviderType.Tencent:
                    request.Parameters.Insert(0, new SNSParameter(SNSParametersConstants.PAGE_FLAG, pageflag));

                    request.Parameters.Insert(0, new SNSParameter(SNSParametersConstants.REQ_NUM, pagecount + string.Empty));
                    var firstItem = items.LastOrDefault();
                    if (firstItem != null)
                    {
                        var id = firstItem.Item.Id;
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.LAST_ID, id + string.Empty));
                        var pagetime = firstItem.Item.Timestamp;
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.PAGE_TIME, pagetime + string.Empty));
                    }
                    else
                    {
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.LAST_ID, 0 + string.Empty));
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.PAGE_TIME, 0 + string.Empty));
                    }
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.NAME, User.AccountName));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.TYPE, 3 + string.Empty));
                    break;
                default:
                    break;
            }

            _statusSvc.GetTimeline(request, (data, result) =>
            {
                if (!result.IsSuccess)
                {
                    ExecuteOnUIThread(() => { MessageBox.Show(result.Message); Loading = false; });
                    return;
                }

                if (result.PagingInfo != null)
                {
                    _pagingInfo = result.PagingInfo;
                }

                PopupItems<SNSStatusViewModel, SNSStatus>(Items, data, false);
            });

            Loading = true;
        }

        internal void NextPageOfFriends(bool isFirstTime)
        {
            SNSRequest request = null;

            request = new SNSRequest() { Type = SNSType.UserFriends };

            if (!isFirstTime && this.Friends.Count < pagecount)
                return;

            switch (User.ServiceProvider)
            {
                case SNSProviderType.Sina:
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.USER_ID, User.Id.ToString()));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.CURSOR, _cursorFriend.ToString()));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.COUNT, pagecount + ""));
                    break;
                case SNSProviderType.Tencent:
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.REQ_NUM, pagecount + ""));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.START_INDEX, pagecount * (_pageFirends) + string.Empty));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.NAME, User.AccountName));
                    break;
                default:
                    break;
            }

            _userSvc.GetUserList(request, (data, result) =>
            {
                if (!result.IsSuccess)
                {
                    ExecuteOnUIThread(() => { MessageBox.Show(result.Message); Loading = false; });
                    return;
                }
                if (result.PagingInfo != null)
                {
                    _cursorFriend = result.PagingInfo.Cursor;
                }
                PopulateItems(Friends, data);

                ExecuteOnUIThread(() =>
                {
                    Loading = false;
                    if (data != null && data.Count > 0 && OnFriendsRefreshed != null)
                    {
                        _pageFirends++;
                        OnFriendsRefreshed();
                    }
                });
            });

            Loading = true;
        }

        internal void NextPageOfFollowers(bool isFirstTime)
        {
            SNSRequest request = null;
            request = new SNSRequest() { Type = SNSType.UserFollowers };

            if (!isFirstTime && Followers.Count < pagecount)
                return;

            switch (User.ServiceProvider)
            {
                case SNSProviderType.Sina:
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.USER_ID, User.Id.ToString()));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.CURSOR, _cursorFollower.ToString()));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.COUNT, pagecount + ""));
                    break;
                case SNSProviderType.Tencent:
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.REQ_NUM, pagecount + ""));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.START_INDEX, pagecount * (_pageFollowers) + string.Empty));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.NAME, User.AccountName));
                    break;
                default:
                    break;
            }

            _userSvc.GetUserList(request, (data, result) =>
            {
                if (!result.IsSuccess)
                {
                    ExecuteOnUIThread(() => { MessageBox.Show(result.Message); Loading = false; });
                    return;
                }
                if (result.PagingInfo != null)
                {
                    _cursorFollower = result.PagingInfo.Cursor;
                }
                PopulateItems(Followers, data);
                ExecuteOnUIThread(() =>
                {
                    Loading = false;
                    if (data != null && data.Count > 0 && OnFollowersRefreshed != null)
                    {
                        _pageFollowers++;
                        OnFollowersRefreshed();
                    }
                });


            });

            Loading = true;
        }

        internal void RefreshTimeLineOfTweets(bool isFirstTime)
        {
            SNSRequest request = null;
            //long pagetime = 0;
            int pageflag = isFirstTime ? 0 : 2;

            ObservableCollection<SNSStatusViewModel> items = null;

            items = Items;
            request = new SNSRequest() { Type = SNSType.UserStatus };

            if (request == null)
                return;

            switch (User.ServiceProvider)
            {
                case SNSProviderType.Sina:
                    var firstItemSina = items.FirstOrDefault();
                    if (firstItemSina != null)
                    {
                        var id = firstItemSina.Item.Id - 1;
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.SINCE_ID, id + string.Empty));
                    }
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.COUNT, pagecount + string.Empty));
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.USER_ID, User.Id.ToString()));
                    break;
                case SNSProviderType.Tencent:
                    request.Parameters.Insert(0, new SNSParameter(SNSParametersConstants.PAGE_FLAG, pageflag + string.Empty));

                    request.Parameters.Insert(0, new SNSParameter(SNSParametersConstants.REQ_NUM, pagecount + string.Empty));
                    var firstItem = items.FirstOrDefault();
                    if (firstItem != null)
                    {
                        var id = firstItem.Item.Id;
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.LAST_ID, id + string.Empty));
                        var pagetime = firstItem.Item.Timestamp;
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.PAGE_TIME, pagetime + string.Empty));
                    }
                    else
                    {
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.LAST_ID, 0 + string.Empty));
                        request.Parameters.Add(new SNSParameter(SNSParametersConstants.PAGE_TIME, 0 + string.Empty));
                    }
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.NAME, User.AccountName));
                    //request.Parameters.Add(new SNSParameter(SNSParametersConstants.TYPE, 0x8 + string.Empty));
                    break;
                default:
                    request.Parameters.Add(new SNSParameter(SNSParametersConstants.COUNT, pagecount + string.Empty));
                    break;
            }

            _statusSvc.GetTimeline(request, (data, result) =>
            {
                if (!result.IsSuccess)
                {
                    ExecuteOnUIThread(() => { MessageBox.Show(result.Message); Loading = false; });
                    return;
                }
                PopupItems<SNSStatusViewModel, SNSStatus>(Items, data, false);

                if (data != null && data.Count > 0 && OnTweetsRefreshed != null)
                {
                    OnTweetsRefreshed();
                }
            });

            Loading = true;
        }
        static object _syncRoot = new Object();
        private void PopulateItems(ObservableCollection<SNSUser> items, IList<SNSUser> data)
        {

            foreach (var i in data)
            {
                ExecuteOnUIThread<SNSUser>((user) =>
                {
                    items.Add(user);
                }, i);
                Thread.Sleep(80);
            }
            Thread.Sleep(400);
        }

        int pivotSelectedIndex;
        public int PivotSelectedIndex
        {
            get
            {
                return pivotSelectedIndex;
            }
            set
            {
                if (value != pivotSelectedIndex)
                {
                    pivotSelectedIndex = value;
                    RaisePropertyChanged(() => PivotSelectedIndex);
                }
            }
        }


    }
}
